
function isArray (arr) {
  return Object.prototype.toString.call(arr) === "[object Array]";
}

function AvaPen ( ele ) {
  this.options = {
    id: '',
    width: '',
    height: '',
    duration: 10000, //默认10s完成动画
    stepTime: 20, //步进时间，视觉效果，默认50帧
    lineCap: 'round', //线圆角
    stepBetweenPoints: 10,
    showPlay: true,
    scale: 1.2
  };

  //
  this.wrapper = null;
  this.player = null;
  this.playerWrapper = null;
  //点
  this.points = []

  //当前绘制的两个点
  this.startPoint = null;
  this.endPoint = null;
  
  this.currentCount = 0;
  this.actualCount = 0;
  this.currentStep = 0;
  this.totalStep = 0;
  this.timer = null;

  //放大缩小
  this.scaleNumber = 1;
  
  // 当前帧的起止位置
  this.startPosition = [0,0];
  this.endPosition = [0,0];

  if(typeof ele === 'string') {
    this.options.id = ele;
    this.wrapper = document.getElementById(ele);
  } else if (Object.prototype.toString.call(ele) === "[object HTMLDivElement]") {
    this.wrapper = ele;
  // this.createPlayer();
  }
  return this;
}

AvaPen.prototype.setup = function (options) {
  for(let attr in options) {
    this.options[attr] = options[attr];
  } 

  this.createPlayer();

  if(options.background) {
    this.setBackground(options.background);
  } 
  if(options.pointList) {
    this.loadData(options.pointList);
  }
  return this;
}


AvaPen.prototype.createPlayer = function () {
  const id = 'canvasPlayer' + parseInt(Math.random()*100000);
  // this.wrapper = document.getElementById(this.options.id);
  // console.log(this.wrapper,this.wrapper.offsetWidth,this.wrapper.offsetHeight);
  
  if(this.options.showPlay) {
    const content = `<div class="ava-dot-trail-player">
                      <canvas id=${id}></canvas>
                      <div class="controll-bar">
                        <div class="inline-block play">
                          <span class="play-button"></span>
                        </div>
                        <div class="inline-block progress-block">
                          <span class="progress">
                            <span class="pasted"></span>
                            <span class="now"></span>
                          </span>
                        </div>
                        <div class="inline-block zoom-block">
                          <span class="zoom"></span>
                        </div>
                      </div>
                    </div>`;
    this.wrapper.innerHTML = content;
  } else {
    this.wrapper.innerHTML = `<div class="ava-dot-trail-player"><canvas id=${id}></canvas></div>`;
  }
  this.playerWrapper = document.getElementById(id);
  this.player = this.playerWrapper.getContext('2d');
  this.playerWrapper.width = this.wrapper.offsetWidth;
  this.playerWrapper.height = this.wrapper.offsetHeight;
  // 返回自己方便链式调用
  const that = this;
  // console.log($(this.playerWrapper));
  $(this.wrapper).find('.play-button').click(function() {
    that.play();
    $(that.wrapper).find('.play-button').hide();
  })
  $(this.wrapper).find('.zoom').click(function() {
    // $(that.playerWrapper)    
    // that.playerWrapper.width = 1600;
    // that.playerWrapper.height = 900;
    that.scale.call(that);
  })
  $(document).click(function(e) {
    const _con = $(that.wrapper);
    console.log(_con);
    if(!_con.is(e.target) && _con.has(e.target).length === 0) {
      that.zoomOut();
    }
  })
  return this;
}

AvaPen.prototype.loadData = function (data) {
  if(isArray(data)) {
    this.points = data;
    //初始化
    this.init();

    //计算完成两个点的时间
    this.drawCompletedPicture();
    return this;
  } else {
    throw new Error('data should be a Array');
  }
}

AvaPen.prototype.init = function () {
  // this.player.height = this.player.width * 9 / 16;
  let player = document.createElement('canvas');
  this.player.lineCap = this.options.lineCap;
  this.clearAll();
}

AvaPen.prototype.scale = function () {
  if(this.wrapper.offsetWidth*this.options.scale<window.innerWidth && this.wrapper.offsetHeight*this.options.scale < window.innerHeight) {
    $(this.wrapper).addClass('fixed_center').css('width',this.wrapper.offsetWidth*this.options.scale).css('height',this.wrapper.offsetHeight*this.options.scale)
    this.playerWrapper.width = this.wrapper.offsetWidth;
    this.playerWrapper.height = this.wrapper.offsetHeight;
    this.scaleNumber = this.options.scale * this.scaleNumber
    this.loadData(this.points);
  } else {
    this.zoomOut();
  }
}


AvaPen.prototype.zoomOut = function () {
  $(this.wrapper).removeClass('fixed_center').css('width',this.wrapper.offsetWidth/this.scaleNumber).css('height',this.wrapper.offsetHeight/this.scaleNumber)
  this.playerWrapper.width = this.wrapper.offsetWidth;
  this.playerWrapper.height = this.wrapper.offsetHeight;
  this.scaleNumber = 1;
  this.loadData(this.points);
}


// 清屏
AvaPen.prototype.clearAll = function () {
  this.player.clearRect(0,0,this.playerWrapper.width,this.playerWrapper.height);
  return this;
}

// 还原笔迹
AvaPen.prototype.play = async function () {
  this.clearAll();
  this.currentStep = 0;
  this.animateProgress();
  let currentPoint = this.points[0];
  let nextPoint = null;
  let step = 1;
  this.currentCount = 0;
  this.actualCount = 0;
  while((this.currentCount+step) < this.points.length) {
    if(currentPoint.validEnable) {
      // 该点有效
      if(this.points[this.currentCount+step].validEnable) {
        //下个点也有效
        nextPoint = this.points[this.currentCount+step];
        if (currentPoint.cmd === 2) {
          // 起点是按下
          if (nextPoint.cmd === 2) {
            //两点指令都是按下，前一点改成抬起，画点
            this.drawPoint(currentPoint);
          }
          else {
            // 其他情况画线
            await this.drawLineWithAction(currentPoint,nextPoint);
          }
          currentPoint = nextPoint;
          this.currentCount += step;
          step = 1;
        } else if (currentPoint.cmd === 3) {
          // 当前点指令是抬起
          if(nextPoint.cmd !== 2) {
            // 抬起之后下一个按下按钮才是有效的，其他无效
            step++;
            // continue;
          } else {
            this.drawPoint(currentPoint);
            currentPoint = nextPoint;
            this.currentCount += step;
            step = 1;
          }
        } else if (currentPoint.cmd === 1) {
          // 当前点指令为移动
          if(nextPoint.cmd === 2) {
            //下一点指令为按下，则为画点
            this.drawPoint(currentPoint);
          } else {
            await this.drawLineWithAction(currentPoint,nextPoint);
          }
          currentPoint = nextPoint;
          this.currentCount += step;
          step = 1;
        } else {
          //无效指令
          currentPoint = nextPoint;
          this.currentCount += step;
          step = 1;
        }
        
      }
      else {
        step++;
      }
      
    } else {
      currentPoint = this.points[this.currentCount+step];
      this.currentCount += step;
      step = 1;  
    }
    console.log(this.currentCount,this.actualCount,this.currentStep,this.totalStep);
    this.actualCount++;
  }
  $(this.wrapper).find('.play-button').show();
}

// 画最终状态
AvaPen.prototype.drawCompletedPicture = function () {
  let currentPoint = this.points[0];
  let nextPoint = null;
  let step = 1;
  let currentCount = 0;
  this.totalStep = 0;
  while((currentCount+step) < this.points.length) {
    if(currentPoint.validEnable) {
      // 该点有效
      if(this.points[currentCount+step].validEnable) {
        //下个点也有效
        nextPoint = this.points[currentCount+step];
        if (currentPoint.cmd === 2) {
          // 起点是按下
          if (nextPoint.cmd === 2) {
            //两点指令都是按下，前一点改成抬起，画点
            this.drawPoint(currentPoint);
            //点，算一步
            // this.totalStep++;
          }
          else {
            // 其他情况画线
            this.drawLine(currentPoint,nextPoint);
            //进度条用
            this.totalStep+=this.options.stepBetweenPoints;
          }
          currentPoint = nextPoint;
          currentCount += step;
          step = 1;
        } else if (currentPoint.cmd === 3) {
          // 当前点指令是抬起
          if(nextPoint.cmd !== 2) {
            // 抬起之后下一个按下按钮才是有效的，其他无效
            step++;
            // continue;
          } else {
            this.drawPoint(currentPoint);
            currentPoint = nextPoint;
            currentCount += step;
            step = 1;
          }
        } else if (currentPoint.cmd === 1) {
          // 当前点指令为移动
          if(nextPoint.cmd === 2) {
            //下一点指令为按下，则为画点
            this.drawPoint(currentPoint);
          } else {
            this.drawLine(currentPoint,nextPoint);
            //进度条
            this.totalStep+=this.options.stepBetweenPoints;
          }
          currentPoint = nextPoint;
          currentCount += step;
          step = 1;
        } else {
          //无效指令
          currentPoint = nextPoint;
          currentCount += step;
          step = 1;
        }
        
      }
      else {
        step++;
      }
      
    } else {
      currentPoint = this.points[currentCount+step];
      currentCount += step;
      step = 1;  
    }
  }
}

// 画线
AvaPen.prototype.drawLine = function (start,end) {

  const startPoint = this.convertCoordinate(start);
  const endPoint = this.convertCoordinate(end);
  this.player.beginPath();
  this.player.strokeStyle = endPoint.color;
  // this.player.lineWidth = endPoint.lineWidth;
  this.player.lineWidth = endPoint.lineWidth*this.playerWrapper.width/1920;
  this.player.moveTo(startPoint.x,startPoint.y);
  this.player.lineTo(endPoint.x,endPoint.y);
  this.player.stroke();
  this.player.closePath();
}

// 画点
AvaPen.prototype.drawPoint = function (srcPoint) {
  const point = this.convertCoordinate(srcPoint);
  this.player.beginPath();
  this.player.fillStyle = point.color;
  this.player.arc(point.x,point.y,point.lineWidth*this.playerWrapper.width/1920/2,0,Math.PI*2);
  this.player.fill();
  this.player.closePath();
}

AvaPen.prototype.genPathPoints = function (start,end,count) {
  const xStep = (end.x - start.x)/count;
  const yStep = (end.y - start.y)/count;
  let arr = [start];
  for(let i = 1; i < count-1; i++) {
    arr.push(Object.assign({},end,{
      x: start.x + xStep*i,
      y: start.y + yStep*i
    }))
  }
  arr.push(end);
  return arr;
}

function waitSec (s) {
  // return setTimeout(function(){return Promise.resolve()},s);
  return new Promise(res => {
    setTimeout(res,s);
  })
}

AvaPen.prototype.drawLineWithAction = async function (startPoint,endPoint) {
  let count = 0;
  let pathPoints = this.genPathPoints(startPoint,endPoint,this.options.stepBetweenPoints); 
  while(count < this.options.stepBetweenPoints-1) {
    this.drawLine(pathPoints[count],pathPoints[count+1]);
    await waitSec(this.options.stepTime);
    count ++;
  }
  return Promise.resolve();
}

AvaPen.prototype.setBackground = function (url) {
  this.playerWrapper.style.backgroundImage = "url('"+url+"')";
  this.playerWrapper.style.backgroundSize = "cover";
}


AvaPen.prototype.convertCoordinate = function (point) {
  return Object.assign({},point,{
    x: point.x * this.playerWrapper.width / 1920,
    y: point.y * this.playerWrapper.height / 1080
  }) 
}

//进度条设置
AvaPen.prototype.setProgress = function () {
  // $(this.wrapper).find('.now').animate({'left':parseInt(this.actualCount*100/this.points.length)+"%"},20,'linear');
  // $(this.wrapper).find('.pasted').animate({'width':parseInt(this.actualCount*100/this.points.length)+"%"},20,'linear');
  // $(this.wrapper).find('.now').animate({'left':parseInt(this.currentStep*100/this.totalStep)+"%"},this.options.stepTime,'linear');
  // $(this.wrapper).find('.pasted').animate({'width':parseInt(this.currentStep*100/this.totalStep)+"%"},this.options.stepTime,'linear');
  $(this.wrapper).find('.now').css('left',"0%");
  $(this.wrapper).find('.pasted').css('width',"0%");
}

AvaPen.prototype.animateProgress = function () {
  // this.currentStep = 0;
  const that = this;
  // console.log('+++++',that.currentStep,that.totalStep)
  // that.currentStep++;
  // clearTimeout(this.timer);
  // if(that.currentStep<that.totalStep) {
  //   this.timer = setTimeout(()=>that.animateProgress.call(this),that.options.stepTime-20);
  // }
  this.setProgress();
  $(this.wrapper).find('.now').animate({'left':"100%"},this.options.stepTime*this.totalStep,'linear');
  $(this.wrapper).find('.pasted').animate({'width':"100%"},this.options.stepTime*this.totalStep,'linear');
}


export default AvaPen